package com.bidevalution.support.util;

import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.Zip4jConstants;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;

/**
 * @description:文件解压缩工具类(zip4j实现)
 * @author: xiayf
 * @date: 2019-07-05 14:51
 */
public class ZipUtil {

    private static Logger log = Logger.getLogger(ZipUtil.class);

    /**
     * 压缩文件并加密（支持文件压缩和文件夹压缩）
     *
     * @param src    需要压缩文件的目录，可以是文件目录也可以是文件夹目录
     * @param dest   压缩后的文件目录
     * @param is     是否对目录进行压缩（当src是文件夹目录时）true 是 false 否
     * @param passwd 压缩密码
     * @throws Exception
     */
    public static void zip(String src, String dest, boolean is, String passwd) throws Exception {

        File srcfile = new File(src);
        //创建目标文件
        String destname = buildDestFileName(srcfile, dest);
        ZipParameters par = new ZipParameters();
        par.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
        par.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
        if (StringUtils.isNotBlank(passwd)) {
            par.setEncryptFiles(true);
            par.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD);
            par.setPassword(passwd.toCharArray());
        }
        try {
            ZipFile zipfile = new ZipFile(destname);
            if (srcfile.isDirectory()) {
                if (!is) {
                    File[] listFiles = srcfile.listFiles();
                    if (listFiles != null) {
                        ArrayList<File> temp = new ArrayList<File>();
                        Collections.addAll(temp, listFiles);
                        zipfile.addFiles(temp, par);
                    }
                } else {
                    zipfile.addFolder(srcfile, par);
                }
            } else {
                zipfile.addFile(srcfile, par);
            }
        } catch (ZipException e) {
            log.error(e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 解压加密的压缩文件
     *
     * @param src    需要解压的文件目录
     * @param dest   存放解压文件目录
     * @param passwd 解压密码
     * @throws Exception
     */
    public static void unZip(String src, String dest, String passwd) throws Exception {
        File zipfile = new File(src);
        try {
            ZipFile zfile = new ZipFile(zipfile);
            //在GBK系统中需要设置
            zfile.setFileNameCharset("GBK");
            if (!zfile.isValidZipFile()) {
                throw new Exception("压缩文件不合法，可能已经损坏！");
            }
            File file = new File(dest);
            if (file.isDirectory() && !file.exists()) {
                file.mkdirs();
            }
            if (zfile.isEncrypted()) {
                zfile.setPassword(passwd.toCharArray());
            }
            zfile.extractAll(dest);
        } catch (ZipException e) {
            log.error(e.getMessage(), e);
            throw e;
        }
    }


    /**
     * 获取压缩文件名称
     *
     * @param srcfile
     * @param dest
     * @return
     */
    private static String buildDestFileName(File srcfile, String dest) {
        if (StringUtils.isBlank(dest)) {
            //没有给出目标路径时
            if (srcfile.isDirectory()) {
                dest = srcfile.getParent() + File.separator + srcfile.getName() + ".zip";
            } else {
                String filename = srcfile.getName().substring(0, srcfile.getName().lastIndexOf("."));
                dest = srcfile.getParent() + File.separator + filename + ".zip";
            }
        } else {
            //路径的创建
            createPath(dest);
            if (dest.endsWith(File.separator)) {
                String filename = "";
                if (srcfile.isDirectory()) {
                    filename = srcfile.getName();
                } else {
                    filename = srcfile.getName().substring(0, srcfile.getName().lastIndexOf("."));
                }
                dest += filename + ".zip";
            }
        }
        return dest;
    }

    /**
     * 路径创建
     *
     * @param dest
     */
    private static void createPath(String dest) {
        File destDir = null;
        if (dest.endsWith(File.separator)) {
            //给出的是路径时
            destDir = new File(dest);
        } else {
            destDir = new File(dest.substring(0, dest.lastIndexOf(File.separator)));
        }
        if (!destDir.exists()) {
            destDir.mkdirs();
        }
    }
}
